﻿using System;
using Yanesdk.Draw;

namespace ADV_Evaluator {

    /// <summary>
    /// テクスチャに座標とかアルファ値とかを一緒に持たせたクラス。
    /// </summary>
    class MySprite : IDisposable { 

        private GlTexture texture;
        private Point location;
        private Rect srcRect;
        private Size destSize;
        private double alpha;
        private bool visible;
        private int fadeinDuration, fadeoutDuration;
        private int fadeinCount, fadeoutCount;
        

        public delegate void FadeEndedDelegate();
        /// <summary>
        /// フェードイン／フェードアウト終了時に呼ばれる
        /// </summary>
        public FadeEndedDelegate FadeEnded;

		public string TextureName
		{
			get { return texture.FileName; }
		}
        /// <summary>
        /// 位置
        /// </summary>
        public Point Location {
            get { return location; }
            set { location = value; }
        }
        /// <summary>
        /// X座標
        /// </summary>
        public float X {
            get { return location.X; }
            set { location.X = value; }
        }
        /// <summary>
        /// Y座標
        /// </summary>
        public float Y {
            get { return location.Y; }
            set { location.Y = value; }
        }
        /// <summary>
        /// 幅
        /// </summary>
        public float Width {
            get { return texture.Width; }
        }
        /// <summary>
        /// 高さ
        /// </summary>
        public float Height {
            get { return texture.Height; }
        }
        /// <summary>
        /// 転送元矩形
        /// </summary>
        public Rect SrcRect {
            get { return srcRect; }
            set { srcRect = value; }
        }
        /// <summary>
        /// 転送先サイズ
        /// </summary>
        public Size DestSize {
            get { return destSize; }
            set { destSize = value; }
        }
        /// <summary>
        /// アルファ値
        /// </summary>
        /// <remarks>フェードの計算の都合上、値はdoubleで持っている</remarks>
        public byte Alpha {
            get { return (byte)alpha; }
            set { alpha = (value > 255) ? 255 : (value < 0) ? 0d : value; }
        }

		public double DblAlpha
		{
			set { alpha = value; }
		}
        /// <summary>
        /// 可視状態
        /// </summary>
        public bool Visible {
            get { return visible; }
            set { visible = value; }
        }
        /// <summary>
        /// エフェクト実行中かどうか
        /// </summary>
        public bool Effecting {
            get { return (fadeinCount >= 0 && fadeoutCount >= 0); }
        }
		public int FadeinDuration
		{
			get { return this.fadeinDuration; }
			set { fadeinDuration = value; }
		}
		public int FadeoutDuration
		{
			get { return this.fadeoutDuration; }
			set { fadeoutDuration = value; }
		}
		public int FadeinCount
		{
			get { return this.fadeinCount; }
			set { fadeinCount = value; }
		}
		public int FadeoutCount
		{
			get { return this.fadeoutCount; }
			set { fadeoutCount = value; }
		}


        /// <summary>
        /// 初期値を指定したコンストラクタ
        /// </summary>
        /// <param name="texture">テクスチャ</param>
        /// <param name="location">位置</param>
        public MySprite(GlTexture texture, Point location) {
            this.texture = texture;
            this.location = location;
            if (texture.Loaded) {
                this.srcRect = new Rect(0, 0, texture.Width, texture.Height);
                this.destSize = new Size(texture.Width, texture.Height);
            }
            this.alpha = 255;
            this.visible = true;
            this.fadeinCount = this.fadeoutCount = -1;
        }
        /// <summary>
        /// 初期値を指定しないコンストラクタ
        /// </summary>
        public MySprite() : this(new GlTexture(), new Point(0, 0)) {
        }
        /// <summary>
        /// 読み込むファイル名を指定したコンストラクタ
        /// </summary>
        /// <param name="filename">ファイル名</param>
        public MySprite(string filename) : this() {
            Load(filename);
        }


        /// <summary>
        /// テクスチャに画像を読み込む
        /// </summary>
        /// <param name="filename"></param>
        public void Load(string filename) {
            texture.Load(filename);
            srcRect = new Rect(0, 0, texture.Width, texture.Height);
            destSize = new Size(texture.Width, texture.Height);
        }

        /// <summary>
        /// テクスチャに.NetのBitmapを読み込む
        /// </summary>
        /// <param name="bitmap"></param>
        /// [2008/04/27] Luice 新規作成
        public void Load_Bitmap(System.Drawing.Bitmap bitmap)
        {
            texture.SetBitmap(bitmap);
            srcRect = new Rect(0, 0, texture.Width, texture.Height);
            destSize = new Size(texture.Width, texture.Height);
        }


        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="system"></param>
        public void Update(GameSystem system) {
            // ロードされていなければ実行しない
            if (!texture.Loaded) {
                return;
            }

            // フェードイン
            if (fadeinCount >= 0) {
                fadeinCount--;
                alpha += (255.0 / fadeinDuration);
                if (fadeinCount < 0) {
                    alpha = 255;
                    if (FadeEnded != null) {
                        FadeEnded();
                    }
                }
            }
            // フェードアウト
            if (fadeoutCount >= 0) {
                fadeoutCount--;
                alpha -= (255.0 / fadeoutDuration);
                if (fadeoutCount < 0) {
                    alpha = 0;
                    if (FadeEnded != null) {
                        FadeEnded();
                    }
                }
            }
            
            // 見えるときのみ転送する
            if (visible) {
                system.Screen.SetColor(255, 255, 255, (int)alpha);
                system.Screen.Blt(texture, (int)X, (int)Y, srcRect, destSize);
                system.Screen.ResetColor();
            }
        }

        /// <summary>
        /// 解放。一度解放するともうLoadは出来ない。
        /// </summary>
        public void Dispose() {
            texture.Dispose();
        }
        /// <summary>
        /// 解放。Disposeと違い再度Loadすることができる。
        /// </summary>
        public void Release() {
            texture.Release();
        }

        /// <summary>
        /// 透明状態から徐々にはっきりさせるエフェクトを開始
        /// </summary>
        /// <param name="duration">エフェクトにかけるフレーム数</param>
        public void Fadein(int duration) {
            if (duration <= 0) {
                return;
            }
            fadeinDuration = fadeinCount = duration;
            alpha = 0;
        }

        /// <summary>
        /// 徐々に透明状態にするエフェクトを開始
        /// </summary>
        /// <param name="duration">エフェクトにかけるフレーム数</param>
        public void Fadeout(int duration) {
            if (duration <= 0) {
                return;
            }
            fadeoutDuration = fadeoutCount = duration;
            alpha = 255;
        }

    }

}
